#!/usr/bin/env python
# -*- coding: utf-8 -*-
#
# Copyright @ 2014 OPS, Qunar Inc. (qunar.com)
#
# Author: tingfang.bao <tingfang.bao@qunar.com>
# DateTime: 15-3-5 下午6:56
import sqlite3

from flask import Flask, g, render_template, session, abort, request, flash, redirect, url_for
import os
import logging

app = Flask(__name__)

LOG = app.logger
# 如何在log handler中设定了级别，这里就必须设定级别，否则不会生效的
LOG.setLevel(logging.DEBUG)

# 本module中，所有大写的全局变量
app.config.from_object(__name__)

# 默认值
app.config.update({
    "DATABASE": os.path.join(app.root_path, "flaskr.db"),
    "DEBUG": True,
    "SECRET_KEY": "1234",
    "USERNAME": "admin",
    "PASSWORD": "default"
})

# 读取环境变量,指向一个文件key=value,用于覆盖上面的默认配置
app.config.from_envvar("FLASK_SETTINGS", silent=True)

print '当前应用所在位置:', app.root_path


def connect_db():
    # SQLAlchemy可以屏蔽这层,可以不用考虑,与flask没什么关系
    rv = sqlite3.connect(app.config['DATABASE'])
    rv.row_factory = sqlite3.Row
    return rv


def get_db():
    # 可以在g对象中,关联任何对象
    if 'sqlite_db' not in g:
        g.sqlite_db = connect_db()
    return g.sqlite_db


@app.teardown_appcontext
def close_db(error):
    # TODO: 搞清楚teardown_appcontext何时发生
    # HTTP请求来的时候,创建app_context,http请求结束时,销毁app_context
    # teardown_appcontext发生的两个条件
    # 1. http 请求正常结束(也就是参数error为None)
    # 2. 发生异常,异常通过参数error传进来
    if hasattr(g, "sqlite_db"):
        g.sqlite_db.close()


@app.before_request
def before_request():
    print 'call before request...'


@app.after_request
def after_request(response):
    print 'call after request...'
    return response


def init_db():
    # 这里完全可以不用与app有任何关系,为的使用能方便的获取文件资源
    # 并且可以在命令行中直接调用
    # from app import init_db
    # init_db()
    with app.app_context():
        db = get_db()
        with app.open_resource("schema.sql", mode="r") as f:
            db.cursor().executescript(f.read())
        db.commit()


# 创建视图界面


@app.route("/")
def show_entries():
    db = get_db()
    cur = db.execute("SELECT title, text FROM entries ORDER BY id DESC ")
    entries = cur.fetchall()
    LOG.info('test info haha...')
    return render_template("show_entries.html", entries=entries)


@app.route("/add", methods=["POST"])
def add_entry():
    # 也可以 if Not session.get('logged_in'), 不过我喜欢下面的方式
    if "logged_in" not in session:
        abort(401)

    db = get_db()
    title = request.form['title']
    text = request.form['text']
    db.execute('INSERT INTO entries(title, text) VALUES (?,?)', [title, text])
    db.commit()
    flash("New entry was successfully posted")
    return redirect(url_for("show_entries"))


@app.route("/login", methods=['GET', 'POST'])
def login():
    error = None
    if request.method == 'POST':
        username = request.form['username']
        password = request.form['password']
        if username != app.config['USERNAME']:
            error = 'Invalid username'
        elif password != app.config['PASSWORD']:
            error = 'Invalid password'
        else:
            session['logged_in'] = True
            flash('You were logged in')
            return redirect(url_for("show_entries"))
    return render_template("login.html", error=error)


@app.route('/logout')
def logout():
    session.pop("logged_in", None)
    flash('You were logged out')
    return redirect(url_for("show_entries"))

# 下面显示了如何进行日志操作
SENDER = 'flaskr@qunar.com'
SUBJECT = 'FLASKR'
MAILS = ['tingfang.bao@qunar.com']
SMTP_HOST = 'mta2.corp.qunar.com'


# noinspection PyShadowingNames
# 注册了邮件日志
def register_mail_log_handler(app, level=logging.DEBUG):
    if not app.debug:
        from logging.handlers import SMTPHandler
        from logging import Formatter

        mail_handler = SMTPHandler(SMTP_HOST, SENDER, MAILS, SUBJECT)
        mail_handler.setLevel(level)
        mail_handler.setFormatter(Formatter('''
Message type: %(levelname)s
Location: %(pathname)s: %(lineno)d
File: %(filename)s
Module: %(module)s
Function: %(funcName)s
Time: %(asctime)s

Message:
%(message)s
        '''))
        app.logger.addHandler(mail_handler)


# 注册了文件日志
# noinspection PyShadowingNames
def register_file_handler(app, level=logging.DEBUG):
    if not app.debug:
        from logging import FileHandler
        from logging import Formatter

        file_handler = FileHandler('./logs/app.log', encoding='utf-8')
        file_handler.setLevel(level)
        file_handler.setFormatter(Formatter('%(asctime)s %(levelname)s: %(message)s  [in %(pathname)s: %(lineno)d]'))
        app.logger.addHandler(file_handler)


# 注册了轮转日志
# noinspection PyShadowingNames
def register_rotating_file_handler(app, level=logging.DEBUG):
    if not app.debug:
        from logging.handlers import RotatingFileHandler
        from logging import Formatter

        rotating_file_handler = RotatingFileHandler("./logs/app.r.log", encoding='utf-8', maxBytes=5242880, backupCount=5)
        rotating_file_handler.setLevel(level)
        rotating_file_handler.setFormatter(
            Formatter('%(asctime)s %(levelname)s: %(message)s  [in %(pathname)s: %(lineno)d]'))
        app.logger.addHandler(rotating_file_handler)


# 注册syslog 可以查看/var/log/syslog文件
# noinspection PyShadowingNames
def register_syslog_handler(app, level=logging.DEBUG):
    if not app.debug:
        from logging.handlers import SysLogHandler
        from logging import Formatter

        syslog_handler = SysLogHandler(address='/dev/log')
        syslog_handler.setLevel(level)
        syslog_handler.setFormatter(
            Formatter('%(asctime)s %(levelname)s: %(message)s  [in %(pathname)s: %(lineno)d]'))
        app.logger.addHandler(syslog_handler)


if __name__ == '__main__':
    # 配置邮件日志系统
    app.debug = False
    register_mail_log_handler(app)
    register_file_handler(app)
    register_rotating_file_handler(app)
    register_syslog_handler(app)

    app.run(host="0.0.0.0", port=8080)